package com.guli.ucenter.controller;

import com.google.gson.Gson;
import com.guli.commonUtils.JwtUtils;
import com.guli.serviceBase.Entity.GuliExcepiton;
import com.guli.ucenter.entity.UcenterMember;
import com.guli.ucenter.service.impl.UcenterMemberServiceImpl;
import com.guli.ucenter.utils.ConstantProperties;
import com.guli.ucenter.utils.HttpClientUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;

/**
 * @author zxc
 * @date 2023/04/17 15:34
 **/
@Api(description = "整合微信授权")
@Controller
// 若是使用@RestController注解的话，所返回的是数据，并不会重定向（redirect）到另一个地址;
@RequestMapping("/api/ucenter/wx")
//@CrossOrigin // 解决跨域问题
public class WxApiController {

    @Autowired
    private UcenterMemberServiceImpl memberService;

    @ApiOperation(value = "生成微信登录验证码")
    @RequestMapping("/login")
    public String getWxCode(){
        // 1.微信开放平台授权baseUrl
        String baseUrl = "https://open.weixin.qq.com/connect/qrconnect" +
                "?appid=%s" +
                "&redirect_uri=%s" +
                "&response_type=code" +
                "&scope=snsapi_login" +
                "&state=%s" +
                "#wechat_redirect";
        // 2.获取重定向地址，对其使用url编码进行加密
        String redirectUrl = ConstantProperties.REDIRECT_URL;
        try {
            redirectUrl = URLEncoder.encode(redirectUrl, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            throw new GuliExcepiton(20001 , "对于重定向地址进行URL编码失败");
        }

        // 防止csrf攻击（跨站请求伪造攻击）
        //String state = UUID.randomUUID().toString().replaceAll("-", "");//一般情况下会使用一个随机数
        String state = "imhelen";//为了让大家能够使用我搭建的外网的微信回调跳转服务器，这里填写你在ngrok的前置域名
        System.out.println("state = " + state);

        // 生成qrcodeUrl
        String qrcodeUrl = String.format(
                baseUrl,
                ConstantProperties.APP_ID,
                redirectUrl,
                state);

        return "redirect:" + qrcodeUrl;
    }

    // 获取授权用户信息;
    @ApiOperation(value = "微信授权登录后回调")
    @GetMapping("/callback")
    public String callback(String code , String state){
        // 1.微信用户授权登录后，获取到所返回的临时票据code;
        System.out.println("code :　" + code);
        // code值，是临时票据；
        // 后续根据code值 + appId + appSecret，是能够获取到所登录用户的AccessToken和OpenId;
        System.out.println("state : " + state);

        // 2.向认证服务器发送请求换取access_token和open_id
        String baseAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token" +
                "?appid=%s" +
                "&secret=%s" +
                "&code=%s" +
                "&grant_type=authorization_code";
        // (1)拼接成所要获取accessToken的请求地址;
        String accessTokenUrl = String.format(baseAccessTokenUrl,
                ConstantProperties.APP_ID,
                ConstantProperties.APP_SECRET,
                code);
        // (2)即，需要通过HttpClientUtils工具类，来发送http请求;
        String result = null;
        try {
            result = HttpClientUtils.get(accessTokenUrl);
            System.out.println("getAccessToken ====> " + result);
        } catch (Exception e) {
            e.printStackTrace();
            throw new GuliExcepiton(20001 , "获取该用户的accessToken失败！！！");
        }

        // (2)通过gson，将json字符串转化为map集合，从而获取到access_token和open_id值;
        Gson gson = new Gson();
        HashMap hashMap = gson.fromJson(result, HashMap.class);
        String accessToken = (String)hashMap.get("access_token");
        String openId = (String)hashMap.get("openid");

        // 3.查询该用户是否存在本数据库中
        UcenterMember member = memberService.getMemberByOpenId(openId);
        if(member == null){
            // 数据库中不存在当前用户信息，则需要将该用户信息添加到数据库中;
            System.out.println("新用户注册~~~");

            // 4.访问微信的资源服务器，获取用户信息
            String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo" +
                    "?access_token=%s" +
                    "&openid=%s";
            String userInfoUrl = String.format(baseUserInfoUrl, accessToken, openId);
            // (1)获取包含用户信息的json字符串
            String userInfo = null;
            try {
                userInfo = HttpClientUtils.get(userInfoUrl);
                System.out.println("useInfo ====>  " + userInfo);
            } catch (Exception e) {
                e.printStackTrace();
                throw new GuliExcepiton(20001, "获取用户信息失败!!!");
            }

            // (2)解析获取所获得用户信息所对应的JSON字符串
            HashMap user = gson.fromJson(userInfo, HashMap.class);
            String nickname = (String)user.get("nickname");
            String headimgurl = (String)user.get("headimgurl");
            // (3)新用户添加到数据库中
            UcenterMember newMember = new UcenterMember();
            newMember.setNickname(nickname);
            newMember.setAvatar(headimgurl);
            newMember.setOpenid(openId);
            memberService.save(newMember);

        }
        String token = JwtUtils.getJwtToken(member.getId() , member.getNickname());
        return "redirect:http://localhost:3000?token=" + token;
    }
    // TODO 为什么需要调用两次 根据token去查询用户信息？？？
}
